package cn.fancylab.template.util;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 序列化工具
 * 
 * 采用注解控制类型的序列化和反序列化，常用注解如下：
==类注解==
1、忽略多个属性
@JsonIgnoreProperties({"prop1", "prop2"})
@JsonIgnoreProperties(ignoreUnknown=true)

2、反序列化处理多态类型
@JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY,property=”class”) 

==方法注解==
1、忽略某个属性
@JsonIgnore

2、按照规定的属性名称序列化
@JsonProperty("prop")

3、自定义序列化规则
    @JsonSerialize(using=DateSerialize.class)
    public Date getCreateTime() {
     return createTime;
    }

4、强制按照子类反序列化，或者强制按照父类序列化
@JsonSerialize(as=BaseClass.class)或者@JsonSerialize(typing=Typing.STATIC) 
@JsonDeserialize(as=SubClass.class)
@JsonDeserialize(using=DateDeserialize.class)
有的放在get方法上，有的在set上
 *
 */
public abstract class JsonUtil {
	
	private static ObjectMapper objectMapper = new ObjectMapper();
	
	/**
	 * 序列化
	 * @param object 对象
	 * @return json字符串
	 */
	public static String serialize(Object object) {
		return serialize(object, null);
	}
	
	/**
	 * 序列化
	 * @param object 对象
	 * @return json字符串
	 */
	public static <T> String serialize(Object object, Class<T> clazz) {
		try {
			Writer write = new StringWriter();
			if (clazz != null) {
				objectMapper.writerWithType(clazz).writeValue(write, object);
			} else {
				objectMapper.writeValue(write, object);
			}
			
			String json = write.toString();
			return json;
		} 
		catch (JsonProcessingException ex) {
			throw new RuntimeException("Could not write JSON: " + ex.getMessage(), ex);
		} 
		catch (IOException ex) {
			throw new RuntimeException("Could not write JSON: " + ex.getMessage(), ex);
		}
	}
	/**
	 * 序列化
	 * @param object 对象
	 * @return json字符串
	 */
	public static <T> String serializeWithDateFormatCannotDeserialize(Object object, Class<T> clazz,SimpleDateFormat sdf) {
		objectMapper.getSerializationConfig().with(sdf);
		try {
			Writer write = new StringWriter();
			if (clazz != null) {
				objectMapper.writerWithType(clazz).writeValue(write, object);
			} else {
				objectMapper.writeValue(write, object);
			}
			
			String json = write.toString();
			return json;
		} 
		catch (JsonProcessingException ex) {
			throw new RuntimeException("Could not write JSON: " + ex.getMessage(), ex);
		} 
		catch (IOException ex) {
			throw new RuntimeException("Could not write JSON: " + ex.getMessage(), ex);
		}
	}
    /**
     * 反序列化
     * @param json json字符串
     * @param clazz 类型
     * @return 对象
     */
    @SuppressWarnings({ "unchecked", "deprecation" })
	public static <T> T deserialize(String json,Class<T> clazz) {
        try {
            JavaType javaType = objectMapper.constructType(clazz);
            Object object = objectMapper.readValue(json, javaType);
            return (T)object;
        }
        catch (JsonProcessingException ex) {
            throw new RuntimeException("Could not read JSON: " + ex.getMessage(), ex);
        }
        catch (IOException ex) {
            throw new RuntimeException("Could not read JSON: " + ex.getMessage(), ex);
        }
    }
    /**
     * 反序列化JSON
     * 
     * @param <T> 返回对象
     * @param json json串
     * @param typeRef 类型
     * @return JSON串返回的对象
     */
    @SuppressWarnings("unchecked")
	public static <T> T deserialize(String json, TypeReference<T> typeRef) {
    	try {
			return (T)objectMapper.readValue(json, typeRef);
		} catch (JsonParseException e) {
            throw new RuntimeException("Could not read JSON: " + e.getMessage(), e);
		} catch (JsonMappingException e) {
            throw new RuntimeException("Could not read JSON: " + e.getMessage(), e);
		} catch (IOException e) {
            throw new RuntimeException("Could not read JSON: " + e.getMessage(), e);
		} 
    }
}